
CUtil = function () {
};

// mil 占쏙옙占쏙옙占쏙옙,  +- 占쏙옙  500ms 占쏙옙占쏙옙 占시곤옙. 
CUtil.RandTime = function(mil) {
	//test 면 바로 ... 
	if (em.test) {
		return 500;
	}
	if ( mil == 0 ) return 0;
	
	var ran =  Math.floor(Math.random()*11) * 50   ;	// 0 ~ 10
	mil = mil + 250 - ran;
	mil = mil < 0 ? 100: mil; // min 100,, 
	return mil;
};


CUtil.TimeDiff = function(atime, btime) {
	// return atime.getTime() - btime.getTime();;
	return atime - btime;
};

CUtil.TimeDiffNow = function(atime) {
	var curtime = $.now();
	return CUtil.TimeDiff(atime, curtime);
	// return atime.getTime() - today.getTime();;
};

CUtil.TimeDiffNowAbs = function(atime) {
	var curtime = $.now();
	return Math.abs(CUtil.TimeDiff(atime, curtime));
};

CUtil.TimeToString = function(d) {
	if ( !d ) return;
	return d.getHours() + ':' + d.getMinutes() +':' + d.getSeconds(); 
};


CUtil.SecToString = function(s) {
	if (s === undefined) return '0';
	return '' + Math.floor(s/3600) + ':' +  Math.floor(s/60) % 60  + ':' + s % 60;
};



CUtil.commify = function (n) {
  var reg = /(^[+-]?\d+)(\d{3})/;   // �뺢퇋��
  n += '';                          // �レ옄瑜�臾몄옄�대줈 蹂�솚

  while (reg.test(n))
    n = n.replace(reg, '$1' + ',' + '$2');

  return n;
};

CUtil.findIdxArrByProperty = function (array, el, property) {
	var i;
	if ( !array ) {
		return -1;
	}
	for ( i=0; i < array.length; i++ ) {
		if ( el[property] === array[i][property]){
			return i;
		} 
	}
    return -1;
};

CUtil.findElArrById = function (array, id) {
    var obj = array.filter(function (val) {
        return val.id === id;
    });
    //filter returns an array, and we just want the matching item
    return obj[0];
};

CUtil.findElArrByValPos = function (array, val, pos) {
	if ( !array ) { 		return  undefined; 	}
	var i;
	for ( i=0; i < array.length; i++ ) {
		if ( val === array[i][pos]){
			return array[i];
		} 
	}
    return undefined;
};


CUtil.findActionByCmd = function (array, cmd) {
    var obj = array.filter(function (action) {
        return action.cmd === cmd;
    });
    //filter returns an array, and we just want the matching item
    return obj[0];
}; 

CUtil.saveStorage = function (key, thing) {
	// var string_thing = JSON.stringify(thing);
	
	// set local storage
	localStorage.setItem(key , JSON.stringify(thing));
};

CUtil.getStorage = function (key) {
	// get local storage
	var thing = localStorage.getItem(key);
	 console.log( thing);
	if ( thing &&  ( thing[0] == "\"" || thing[0] == "{" ) ) {
		return JSON.parse(thing);
	}
	return thing;
	// console.log( ' get strogate : ' + ret);
	// return ret;
};

// ret : needO ,  if fail : 0
CUtil.calcNeedO = function (h, da) {
			if ( ! da.h && ! da.n) return 0;
			
			da.h = (da.h === undefined) ? 0 : da.h;
			da.n = (da.n === undefined) ? 0 : da.n;
			
   			var genid = h.gid;
			var def 	= h.c1;

			//get user reserach lv
			var ExAr = CDB.getUserAdvAr();
			var DefAt = CDB.getUserDefForm();
			var GuilHBuf =CDB.getUserGuilHBuf(); 
			var GuilArmBuf =CDB.getUserGuilArmBuf(); 
			
			debug.log(this, ' Study: AdvAr:', ExAr, ' Def Forma: ', DefAt);
			// cal  max sol num :  overload number 
			var da_maxatt = (da.h * 15 * 1.175) * 1.8 + ( da.n * 60 * 1.175) *1.8 ;  // critical 1.8 
			var h_def_with_allybuf = def * (1 + GuilHBuf * 0.05);
			var minO =  Math.round( 
					da_maxatt / 
						(180   // over def : 180 
							* ( 1 + h_def_with_allybuf * 0.005) * ( 1+ ( ExAr + DefAt)/20 )    // �숆컩, 諛⑺깭.
						* ( 1+ GuilArmBuf/100) )  // �숇㏏ 諛⑹뼱 �ㅽ궗 
					);
			
			minO = Math.round ( minO * 1.02); //  �ъ쑀 遺� 1. 01 諛�.

			debug.log(this,  'Ho : ' + da.h + ' ,  Na: : ' + da.n   );
			debug.log(this,  'Calc over num : ' + minO + ' ,  da_maxatt : ' + Math.round(da_maxatt)  
					+ ' H-def: ' + def );
			  
			return minO;
};
   
CUtil.calcMoreB  = function (h, da, myO) {
			if ( ! da.h && ! da.n) return 0;
			
   			var genid = h.gid;
			var def 	= h.c1;

			//get user reserach lv
			var ExAr = CDB.getUserAdvAr();
			var DefAt = CDB.getUserDefForm();
			var GuilHBuf =CDB.getUserGuilHBuf(); 
			var GuilArmBuf =CDB.getUserGuilArmBuf(); 
			
			// cal  max sol num :  overload number 
			var da_maxatt = (da.h * 15 * 1.175) * 1.8 + ( da.n * 60 * 1.175) *1.8 ;  // critical 1.8 
			var h_def_with_allybuf = def * (1 + GuilHBuf * 0.05);

			var OsDef =  Math.round( 
						180   // over def : 180 
							* ( 1 + h_def_with_allybuf * 0.005) * ( 1+ ( ExAr + DefAt)/20 )    // 
						* ( 1+ GuilArmBuf/100)  
					);
			
			var remainforBer = da_maxatt - OsDef * myO;
			console.log(this,  'remainforBer : ' + remainforBer + ' ,  per O Def: : ' + OsDef , ' Os Def' , OsDef*myO   );
			
			var minB =  Math.round( 
					remainforBer / 
						(150   // over def : 180 
							* ( 1 + h_def_with_allybuf * 0.005) * ( 1+ ( ExAr + DefAt)/20 )    // �숆컩, 諛⑺깭.
						* ( 1+ GuilArmBuf/100) )  // �숇㏏ 諛⑹뼱 �ㅽ궗 
					);
			

			console.log(this,  'Ho : ' + da.h + ' ,  Na: : ' + da.n   );
			console.log(this,  'Calc ber num : ' + minB + ' ,  remainforBer : ' + Math.round(remainforBer)  
					+ ' H-def: ' + def );
			  
			return minB;
};   


// cost 와 res 를 주면, 가능 한지,  change 는 얼마 해야 하는 지반환. 
// possisible & exchange.. 
CUtil.calcNeedRes = function (res , cost , spare ) {
	
	var possible = false;
	var moreg = {f:0, w:0, i:0 , total: 0 };
	if ( ! spare )  spare = 10000;
	
	function subRes(a, b) {
		var res = { gt: true};
		for (p in a ) {
			res[p] = a[p] - b[p];
			if( res[p] < 0 )
				res.gt = false; 
			}
		return res;
	}
	
	var diff = subRes(res, cost);
			
	if ( diff.gt ) {
		// possible 
		possible = true;
	} else {
		// 2. less  ==> g-> x : �
		var trans_ratio = { f: 7, w: 16, i: 10 };
	
		for (p in diff) {
			if ( diff[p] < 0 ) {
				moreg[p] += Math.ceil(Math.abs(diff[p] / trans_ratio[p])) + spare; 
				moreg.total +=  moreg[p];
			}
		}	
		
		if ( res.g > cost.g + moreg.total ) {
			possible = true;
		} else {
			possible = false;
		}
	}
 
//{g2f: calc_ret.exchange.f,  g2w: calc_ret.exchange.w, g2i: calc_ret.exchange.i, total:calc_ret.exchange.total } , 
	return {'possible': possible, 'exchange': moreg, 
			'g2f': moreg.f,  'g2w': moreg.w, 'g2i': moreg.i, 'total': moreg.total } ;
};

// calc max possible sol num & req res :
// @ sol_type   
// @ in cur res  
// @ [ret] calc maxnum
CUtil.calcMaxSolNum_ExRes  = function ( sol_type,  res , get_exchage ) {
			var asol_cost  = CDB.SOLS.COST[ sol_type ];
			var cur_res  = em.cstlmgr.getCurCstl().res;
			// ex :   100 200 300  200  
			//  ration : 1.5 1.5 15. 1  
			//   1)  i , w, f  >   g * 1.5  :   go next 
			//  2)  i  < g* 1.5  :    more i  = 200 :  
			//  3 )  w < g * 1.5 : more w = 100 : 
			// 4 )  more -> ratio sum : 50 
			// 5 ) 300 300 300 150 
			//  6 ) sum >  n ( 10 )     try 1 more with  g - n : 190 
			
	 	 	var trans_ratio = { f: 7, w: 16, i: 10 };
	 	 	
	 	 	// sol cost 와 res 를 주면  필요한  변환  g 를 반환. 
		 	function calcExResForMax ( asol_cost, res, moreg ) {
		 	 	var ratio = {}, need_res = 0 , more_res = 0;
		 	 	//var moreg = {};
				for (p in trans_ratio ) {
					if ( p == 'g')  continue; 		//skip 
					ratio[p] =  asol_cost[p] *1.0 / asol_cost.g; // 
					need_res =  res.g * ratio[p];
					if ( p == 'f' ) 	need_res += CDB.getCurUserInfo().MinFood; // remian min food 
		 					
					if (cur_res[p]  > need_res  )  continue;		// skip  //   1)  i , w, f  >   g * 1.5  :   go next 
					
					more_res = need_res - cur_res[p];

					moreg[p] += Math.ceil(Math.abs(more_res / trans_ratio[p])) ; 
					moreg.total +=  moreg[p];
				}
				return moreg;
		 	};
		 	
		 	// res 에서 moreg 에서 ratio 만큼 변환해서  res 를 반환. 
		 	function exchangeRes(res, moreg, ex_ratio ) {
		 		for (p in res  ) {
		 			if ( p == 'g' ) continue;			// g 는  skip  
		 			moreg[p] *=  ex_ratio;		// ex ratio 반영
					res [ p] =  res[p]  + moreg[p] * trans_ratio[p];		// 그만 큼 변환해서 저장.
					res.g -= moreg[p] ;		// g 에서  - 
				}
				return res;
		 	};
		 	
			// if ( moreg.total > 100000 )  retry ;
			var res = cur_res;
			var moreEx = {f:0, w:0, i:0, g:0, total: 0};
		 	moreEx = calcExResForMax (asol_cost , res , moreEx );

		 	while (  moreEx.total > 100000  ) {
			 	moreEx = calcExResForMax (asol_cost , res , moreEx );
			 	// 요구량의 반으로 변환 후 다시 시도. 
			 	exchangeRes( res, moreEx , 0.5 );
		 	}

			// calc  max :: num   
			var min_possibleNum, possible_max=0;
			for (p in res  ) {
					min_possibleNum  =  res[p]  / asol_cost[p];
					if ( min_possibleNum < possible_max ) {
						possible_max = min_possibleNum;
					} 
			}
	
		 	// calc  exchage amount  & store 
		 	if ( get_exchage) {
				var calc_ret = CUtil.calcNeedRes(cur_res, res );
				$.extend ( get_exchage , calc_ret);
		 	}
		 	
			return possible_max;
}

// calc max possible sol num & req res :
// @ req sol num : 
// @ [out] calc maxnum
// @ in cur res  
CUtil.compareRes  = function (a , b) {
				var cost = {};
			for (p in aCost ) {
				cost[p] = aCost[p] * self.input_num;
			}
			// remian min food 
			cost.f += CDB.getCurUserInfo().MinFood;
			
			var res  = em.cstlmgr.getCurCstl().res;

			debug.log( this, ' train Need cost: ', cost);
	
			var calc_ret = CUtil.calcNeedRes(res, cost );
}

// simple compare res.. 
// a >= b  : 1 
// a < b : -1 
CUtil.compareRes  = function (a , b) {
		var res = { gt: true};
		for (p in a ) {
			res[p] = a[p] - b[p];
			if( res[p] < 0 )
				res.gt = false; 
			}
			
		if ( res.gt == false )
			return -1;
		
		return 1;
};





CUtil.sortDistanceFn  =  function(a,b , pos){
				
					var my_x = pos.x;
					var my_y = pos.y;
					//  max 처리 .!!!   10 <- 280 - > 260 :  30 !! 
					// 10 - 260  ; 250 ,   280 - 250 : 30  ,  min ( 250, 30)
					//  50 , 80 : 50 -80 : 30,    280 - 30 = 250 ; 
					// 160, 280 : 120 ,  280 - 120 : 160 
					var diff_ay = Math.min( Math.abs(my_y -a.y) ,  280 - Math.abs(my_y - a.y)  );
					var diff_ax = Math.min( Math.abs(my_x -a.x) ,  280 - Math.abs(my_x - a.x)  );

					var diff_by = Math.min( Math.abs(my_y -b.y) ,  280 - Math.abs(my_y - b.y)  );
					var diff_bx = Math.min( Math.abs(my_x -b.x) ,  280 - Math.abs(my_x - b.x)  );
					
					var dis_a = Math.pow(diff_ax,2) + Math.pow( diff_ay, 2) ;
					var dis_b = Math.pow(diff_bx,2) + Math.pow( diff_by, 2) ;
					
					return dis_a - dis_b;
			};

CUtil.prototype = {

	print_result : function (msg) {
		//	this.dumpobj( $("#result_box") , obj , 1) ;
		//$("#result_box").empty();
		// $("#result_box").append( this.print_obj(obj) );
		$("#result_box").append( msg + '<br/>');
		console.log(msg);
	},	
	
	print_status : function (obj) {
		$("#log_box").empty();
		$("#log_box").append( this.print_obj(obj) );
	},

	print_obj:function(o){ 
		var str=''; 
		for(var p in o){ 
			if(typeof o[p] != 'object'){ 
				str+= p + ': ' + o[p]+'; </br>'; 
			}
			else
			{ 
				str+= p + ': { ' + this.print_obj(o[p]) + '} <br/>'; 
			}
		}
		return str; 
//$('body').append( print(myObject) );
	},	
	
	dumpobj: function(ct , arr , level) {
		var dumped_text = "";
		if(!level) level = 0;

			//The padding given at the beginning of the line.
			var level_padding = "";
			for(var j=0; j < level+1; j++) level_padding += "? ";

				if(typeof(arr) == 'object') { //Array/Hashes/Objects
					for(var item in arr) {
					var value = arr[item];

					if(typeof(value) == 'object') { //If it is an array,
					dumped_text += level_padding + "'" + item + "' ...\n";
					dumped_text += this.dumpobj(ct, value,level+1);
				} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
				}
			}
		} else { //Stings/Chars/Numbers etc.
			dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
		}
		ct.empty();
		ct.append($("<p>").append(dumped_text));
		return dumped_text;
	},
	
 trans : function(str){
//	document.getElementById("unicode").value = replaceAll(escape(str),"%","\\");	
	return replaceAll(escape(str),"%","\\");
},



 detrans : function(str){
//	var str = document.getElementById("unicode2").value;
//	document.getElementById("hangul2").value = unescape(replaceAll(str,"\\","%"));	
	return unescape(replaceAll(str,"\\","%"));
},

 replaceAll : function(strTemp, strValue1, strValue2){
    while(1){
        if( strTemp.indexOf(strValue1) != -1 )
            strTemp = strTemp.replace(strValue1, strValue2);
        else
            break;
    }
    return strTemp;
},

};



function cloneObject(source) {
    for (i in source) {
        if (typeof source[i] == 'source') {
            this[i] = new cloneObject(source[i]);
        }
        else{
            this[i] = source[i];
	}
    }
};
 
